﻿#include "RePackingMp4ByFormatCodeWindow.h"
#include <QFileDialog>
#include <QSize>
#include <QMessageBox>
#include <Qt>
#include <QDebug>

extern "C"
{
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
#include "libavutil/avutil.h"
}


RePackingMp4ByFormatCodeWindow::RePackingMp4ByFormatCodeWindow(QWidget* parent)
	: QWidget(parent)
{
	ui.setupUi(this);
	this->setWindowTitle("重新封装MP4，如果是网络流则变为录制流到本地->封装基础代码，使更简洁");
	setAttribute(Qt::WA_DeleteOnClose, true);  // 关闭时自动销毁窗口
}

void RePackingMp4ByFormatCodeWindow::OnSrcFileSelected()
{
	QString filter = "所有文件(*.*)"; //文件过滤器
	QString filePath = QFileDialog::getOpenFileName(this, "选择输入文件", "", filter);
	this->srcFilePath = filePath;
	this->ui.lineEdit_src_path->setText(this->srcFilePath);
}

void RePackingMp4ByFormatCodeWindow::OnDstOutputFileSelected()
{
	QString filter = "所有文件(*.*)"; //文件过滤器
	QString filePath = QFileDialog::getSaveFileName(this, "选择输出文件", "", filter);
	this->dstFilePath = filePath;
	this->ui.lineEdit_target_path->setText(this->dstFilePath);
}

void RePackingMp4ByFormatCodeWindow::OnStartTransfer()
{
	if (this->dstFilePath.isEmpty() || this->srcFilePath.isEmpty()) {
		QMessageBox::information(this, "温馨提示", "参数不对请检查参数");
		return;
	}
	begin_seconds = this->ui.lineEdit_start_time->text().toDouble();//开始截取时间
	end_seconds = this->ui.lineEdit_end_time->text().toDouble();//结束截取时间
	isRunning = true;
	demuxer = new YDemuxer();
	muxer = new YMuxer();
	renderThread = std::make_unique<std::thread>(&RePackingMp4ByFormatCodeWindow::OnTransfer, this);
}

void RePackingMp4ByFormatCodeWindow::OnTransfer()
{

	auto ic = demuxer->Open(this->srcFilePath.toStdString().c_str());
	demuxer->setContext(ic);

	auto oc = muxer->Open(this->dstFilePath.toStdString().c_str());
	muxer->setContext(oc);
	auto o_vs = oc->streams[muxer->GetVideoIndex()];//视频流信息
	auto o_as = oc->streams[muxer->GetAudioIndex()];//音频流信息


	if (demuxer->GetVideoIndex() >= 0)//输入文件中有视频数据
	{
		o_vs->time_base.den = demuxer->GetVideoTimeBase().den;
		o_vs->time_base.num = demuxer->GetVideoTimeBase().num;
		//将输入的视频参数复制到输出中
		demuxer->CopyInCodecParametersToOut(demuxer->GetVideoIndex(), o_vs->codecpar);
	}

	if (demuxer->GetAudioIndex() >= 0)//输入文件中有音频数据
	{
		o_as->time_base.den = demuxer->GetAudioTimeBase().den;
		o_as->time_base.num = demuxer->GetAudioTimeBase().num;
		//将输入的音频参数复制到输出中
		demuxer->CopyInCodecParametersToOut(demuxer->GetAudioIndex(), o_as->codecpar);
	}



	if (begin_seconds > 0 && end_seconds > 0)
	{
		//计算开始的pts和结束的pts
	   //pts = seconds/(num/den)=seconds*(den/num)
		if (demuxer->GetVideoIndex() >= 0 && demuxer->GetVideoTimeBase().num > 0)
		{
			double t = (double)demuxer->GetVideoTimeBase().den / (double)demuxer->GetVideoTimeBase().num;//den分母/num分子
			begin_pts = begin_seconds * t;
			end_pts = end_seconds * t;
			demuxer->Seek(begin_pts, demuxer->GetVideoIndex());
		}

		if (demuxer->GetAudioIndex() >= 0 && demuxer->GetAudioTimeBase().num > 0)
		{
			begin_audio_pts = begin_seconds * ((double)demuxer->GetAudioTimeBase().den / (double)demuxer->GetAudioTimeBase().num);
		}

	}

	//写入头部
	muxer->WriteHead();

	int audio_count = 0;//音频真总数
	int video_count = 0;//视频帧总数
	double total_sec = 0;//总时长

	AVPacket pkt;
	while (isRunning)
	{
		if (!demuxer->Read(&pkt))break;

		// 视频 时间大于结束时间
		if (begin_pts > 0
			&& pkt.stream_index == demuxer->GetVideoIndex()
			&& pkt.pts > begin_pts)
		{
			av_packet_unref(&pkt);
			break;
		}
		if (pkt.stream_index == demuxer->GetVideoIndex())
		{
			muxer->RescaleTime(&pkt, begin_pts, demuxer->GetVideoTimeBase());

			video_count++;
			if (demuxer->GetVideoTimeBase().den > 0)
				total_sec += pkt.duration * ((double)demuxer->GetVideoTimeBase().num / (double)demuxer->GetVideoTimeBase().den);
		}
		else if (pkt.stream_index == demuxer->GetAudioIndex())
		{
			muxer->RescaleTime(&pkt, begin_audio_pts, demuxer->GetAudioTimeBase());
			audio_count++;
		}

		//写入视频帧
		if (!muxer->Write(&pkt))break;
	}
	//写入视频尾部
	muxer->WriteEnd();


	demuxer->Close();
	muxer->Close();
	if (demuxer) {
		delete demuxer;
	}

	if (muxer)
	{
		delete muxer;
	}
	qDebug() << "视频帧:" << video_count;
	qDebug() << "音频帧:" << audio_count ;
	qDebug() << "总时长:" << total_sec ;

	qDebug() << "解封装结束";


}

void RePackingMp4ByFormatCodeWindow::closeEvent(QCloseEvent* event) {
	event->accept();  // 接受关闭事件（允许关闭）
	if (isRunning && renderThread->joinable()) {
		renderThread->join();
		renderThread = nullptr;
	}
	qDebug() << "窗口已关闭";
}

RePackingMp4ByFormatCodeWindow::~RePackingMp4ByFormatCodeWindow()
{
}
